<template>
  <div class="cesium-container" ref="mapRef" >
  </div>
</template>

<script setup>
import { 
  Cartesian3,
  createOsmBuildingsAsync,
  Ion,
  IonImageryProvider,
  Math as CesiumMath, 
  Terrain, 
  Viewer,
  WebMapTileServiceImageryProvider,
  IonWorldImageryStyle,
  ImageryLayer,
  UrlTemplateImageryProvider,
  HeadingPitchRoll,
  KmlDataSource,
  Cartographic,
  DistanceDisplayCondition,
  defined,
  Color,
  GeoJsonDataSource,
  WebMercatorTilingScheme,
  ClassificationType,
  BoundingSphere,
  HorizontalOrigin,
  VerticalOrigin,
  Ellipsoid,
  JulianDate,
  Matrix4,
  VelocityOrientationProperty,
  HermitePolynomialApproximation,
  CzmlDataSource,
  Cesium3DTileset,
  IonResource,
  CustomShader,
  LightingModel,
  Cesium3DTileStyle,
  ScreenSpaceEventHandler,
  ScreenSpaceEventType,
  PostProcessStageLibrary
  } from 'cesium';
import "cesium/Build/Cesium/Widgets/widgets.css";
import config from '../config'

defineProps({
  msg: String,
});
Ion.defaultAccessToken = config.token
const mapRef = ref(null);
let drone;
onMounted(async () => {
  const viewer = new Viewer(mapRef.value, {
    orderIndependentTranslucency: false,
    contextOptions: {
        webgl: {
            alpha: true
        }
    },
    terrain: Terrain.fromWorldTerrain(),
    // 进入页面启动动画
    // shouldAnimate: true
  });   

  viewer.scene.backgroundColor = new Color(0.0, 0.0, 0.0, 0.0);
  // viewer.imageryLayers.remove(viewer.imageryLayers.get(0));

  // const layer = viewer.imageryLayers.addImageryProvider(
  //   await IonImageryProvider.fromAssetId(3812) 3954
  // );
  // viewer.imageryLayers.addImageryProvider(await IonImageryProvider.fromAssetId(3954));
  // 增加谷歌影像底图
  // viewer.imageryLayers.addImageryProvider(new UrlTemplateImageryProvider({
  //                     url: 'http://www.google.cn/maps/vt?lyrs=s&x={x}&y={y}&z={z}',
  //                     tilingScheme: new WebMercatorTilingScheme()
  //                 })
  // );

  viewer.scene.globe.depthTestAgainstTerrain = true;

  var initialPosition = new Cartesian3.fromDegrees(-73.998114468289017509, 40.674512895646692812, 2631.082799425431);
  var initialOrientation = new HeadingPitchRoll.fromDegrees(7.1077496389876024807, -31.987223091598949054, 0.025883251314954971306);
  var homeCameraView = {
    destination : initialPosition,
    orientation : {
        heading : initialOrientation.heading,
        pitch : initialOrientation.pitch,
        roll : initialOrientation.roll
    }
  };
  // 设置视图
  viewer.scene.camera.setView(homeCameraView);
  viewer.scene.globe.enableLighting = true;
   // 重写默认的 home button
  // homeCameraView.duration = 2.0;
  // homeCameraView.maximumHeight = 2000;
  // homeCameraView.pitchAdjustHeight = 2000;
  // homeCameraView.endTransform = Matrix4.IDENTITY;
  // viewer.homeButton.viewModel.command.beforeExecute.addEventListener(function (e) {
  //     e.cancel = true;
  //     viewer.scene.camera.flyTo(homeCameraView);
  // });
  kmlModule(viewer)
  // neighborhoodsGeoJson(viewer)
  // flightModuleCzml(viewer) 
  tilesModule(viewer)
  // 交互
  const overlay = createOverlay()
  viewer.container.appendChild(overlay)
  // 悬停区域边框
  // hoverBorderEvent(viewer, overlay)
  // 悬停高亮
  hoberHighlightEvent(viewer, overlay)
})


const kmlModule = viewer => {
    const kmlOptions = {
      camera : viewer.scene.camera,
      canvas : viewer.scene.canvas,
      clampToGround : true // 选项控制数据是否贴地
    };

  const geocachePromise = KmlDataSource.load('./Source/SampleData/sampleGeocacheLocations.kml', kmlOptions);
  geocachePromise.then(function(dataSource) {
    // Add the new data as entities to the viewer
    viewer.dataSources.add(dataSource);
    // console.log('dataSource::: ', dataSource);
    var geocacheEntities = dataSource.entities.values;
    for (let i = 0; i < geocacheEntities.length; i++) {
        let entity = geocacheEntities[i];
        if (defined(entity.billboard)) {
               // Adjust the vertical origin so pins sit on terrain
          entity.billboard.verticalOrigin = VerticalOrigin.BOTTOM;
          // Disable the labels to reduce clutter
          entity.label = undefined;
          // Add distance display condition
          entity.billboard.distanceDisplayCondition = new DistanceDisplayCondition(10.0, 20000.0);

          var cartographicPosition = Cartographic.fromCartesian(entity.position.getValue(JulianDate.now()));
          var longitude = CesiumMath.toDegrees(cartographicPosition.longitude);
          var latitude = CesiumMath.toDegrees(cartographicPosition.latitude);
          // Modify description
          // Modify description
          var description = '<table class="cesium-infoBox-defaultTable cesium-infoBox-defaultTable-lighter"><tbody>' +
              '<tr><th>' + "Longitude" + '</th><td>' + longitude.toFixed(5) + '</td></tr>' +
              '<tr><th>' + "Latitude" + '</th><td>' + latitude.toFixed(5) + '</td></tr>' +
              '</tbody></table>';
          entity.description = description;
        }
    }
  });
}

const neighborhoodsGeoJson = (viewer) => {
  const geojsonOptions = {
    clampToGround : true
  };
  // 从geojson文件加载行政区多边形边界数据
  const neighborhoodsPromise = GeoJsonDataSource.load('./Source/SampleData/sampleNeighborhoods.geojson', geojsonOptions);
  
  let neighborhoods;
  neighborhoodsPromise.then(function(dataSource) { 
      viewer.dataSources.add(dataSource);
      neighborhoods = dataSource.entities;

      // 获取enity列表遍历
      let neighborhoodEntities = dataSource.entities.values;
      for (var i = 0; i < neighborhoodEntities.length; i++) {
          var entity = neighborhoodEntities[i];

          if (defined(entity.polygon)) {
              // 设置样式代码
              entity.name = entity.properties.neighborhood;
              entity.polygon.material = Color.fromRandom({
                  red : 0.1,
                  maximumGreen : 0.5,
                  minimumBlue : 0.5,
                  alpha : 0.6
              });
              // 设置这个属性让多边形贴地，ClassificationType.CESIUM_3D_TILE 是贴模型，ClassificationType.BOTH是贴模型和贴地
              entity.polygon.classificationType = ClassificationType.TERRAIN;
              // 获取多边形的positions列表 并计算它的中心点
              let polyPositions = entity.polygon.hierarchy.getValue(JulianDate.now()).positions;
              let polyCenter = BoundingSphere.fromPoints(polyPositions).center;
              polyCenter = Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter);
              entity.position = polyCenter;
              // 生成文字标注
              // console.log('entity.name', entity.name);
              entity.label = {
                  text : entity.name + '*',
                  showBackground : true,
                  scale : 0.6,
                  horizontalOrigin : HorizontalOrigin.CENTER,
                  verticalOrigin : VerticalOrigin.BOTTOM,
                  distanceDisplayCondition : new DistanceDisplayCondition(10.0, 8000.0),
                  disableDepthTestDistance : 100.0
              };
          }
      }
  });
}
const flightModuleCzml = (viewer) => {
  // 无人机轨迹
  let dronePromise = CzmlDataSource.load('./Source/SampleData/SampleFlight.czml');
  dronePromise.then(function(dataSource) {
      viewer.dataSources.add(dataSource);
      // 使用id获取在CZML 数据中定义的无人机entity
      drone = dataSource.entities.getById('Aircraft/Aircraft1');
      // // 附加一些三维模型
      drone.model = {
          uri : './Source/SampleData/Models/CesiumDrone.glb',
          minimumPixelSize : 128,
          maximumScale : 1000,
          silhouetteColor : Color.WHITE,
          silhouetteSize : 1
      };
      // 基于无人机轨迹的位置点，自动计算朝向
      drone.orientation = new VelocityOrientationProperty(drone.position);
      // 光滑的路径插值
      drone.position.setInterpolationOptions({
          interpolationDegree : 3,
          interpolationAlgorithm : HermitePolynomialApproximation
      });
      
      viewer.trackedEntityChanged.addEventListener(function() {
        viewer.trackedEntity = drone
      });
  });
} 
// 3Dtiles 
const tilesModule = async(viewer) => {
  // var loadingIndicator = document.getElementById('loadingIndicator');
  // loadingIndicator.style.display = 'block';
  const tileset = await Cesium3DTileset.fromIonAssetId(75343);
  // loadingIndicator.style.display = 'none';
  viewer.scene.primitives.add(tileset)
  let heightOffset = -32;
  let boundingSphere = tileset.boundingSphere;
  let cartographic = Cartographic.fromCartesian(boundingSphere.center);
  let surface = Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
  let offset = Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, heightOffset);
  let translation = Cartesian3.subtract(offset, surface, new Cartesian3());
  tileset.modelMatrix = Matrix4.fromTranslation(translation);
  // console.log(tileset);
  var defaultStyle = new Cesium3DTileStyle({
    color : "color('white')",
    show : true
  });
  var transparentStyle = new Cesium3DTileStyle({
    color : "color('white', 0.5)",
    show : true
});
var heightStyle = new Cesium3DTileStyle({
    color : {
        conditions : [
            ["${Height} >= 300", "rgba(45, 0, 75, 0.5)"],
            ["${Height} >= 200", "rgb(102, 71, 151)"],
            ["${Height} >= 100", "rgb(170, 162, 204)"],
            ["${Height} >= 50", "rgb(224, 226, 238)"],
            ["${Height} >= 25", "rgb(252, 230, 200)"],
            ["${Height} >= 10", "rgb(248, 176, 87)"],
            ["${Height} >= 5", "rgb(198, 106, 11)"],
            ["true", "rgb(127, 59, 8)"]
        ]
    }
});
  tileset.style = heightStyle;
}

const hoverBorderEvent = viewer => {
  const selected = {
    feature: undefined,
    originalColor: new Color()
  }
  const handler = new ScreenSpaceEventHandler(viewer.scene.canvas);
  const silhouetteBlue = PostProcessStageLibrary.createEdgeDetectionStage();
  silhouetteBlue.uniforms.color = Color.BLUE;
  silhouetteBlue.uniforms.length = 0.01;
  silhouetteBlue.selected = [];

  viewer.scene.postProcessStages.add(
    PostProcessStageLibrary.createSilhouetteStage([
      silhouetteBlue
    ])
  );

  handler.setInputAction(function(movement) {
    // var pickedPrimitive = viewer.scene.pick(movement.endPosition);
    const pickedFeature = viewer.scene.pick(movement.endPosition);
    silhouetteBlue.selected = [];

    // Pick a new feature
    hoverWin(viewer, pickedFeature, movement.endPosition);

    if (!defined(pickedFeature)) {
      return;
    }

    // Highlight the feature if it's not already selected.
    if (pickedFeature !== selected.feature) {
      silhouetteBlue.selected = [pickedFeature];
    }
  }, ScreenSpaceEventType.MOUSE_MOVE);
}
// 悬停高亮
const hoberHighlightEvent = (viewer, overlay) => {
  const selected = {
    feature: undefined,
    originalColor: new Color()
  }
  const highlighted = {
    feature: undefined,
    originalColor: new Color(237, 11, 43, 0.8),
  };
  viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(
    movement
  ) {
    
    // If a feature was previously highlighted, undo the highlight
    if (defined(highlighted.feature)) {
      highlighted.feature.color = highlighted.originalColor;
      highlighted.feature = undefined;
    }
    // Pick a new feature
    const pickedFeature = viewer.scene.pick(movement.endPosition);
    hoverWin(viewer, overlay, pickedFeature, movement.endPosition);
    if (!defined(pickedFeature)) {
      return;
    }
    
    // Highlight the feature if it's not already selected.
    if (pickedFeature !== selected.feature) {
      highlighted.feature = pickedFeature;
      Color.clone(
        pickedFeature.color,
        highlighted.originalColor
      );
      pickedFeature.color = Color.fromCssColorString('#ED0B2B').withAlpha(0.5)
    }
  },
  ScreenSpaceEventType.MOUSE_MOVE);
}

const createOverlay = () => {
  const nameOverlay = document.createElement("div")
  nameOverlay.className = "backdrop"
  nameOverlay.style.display = "none"
  nameOverlay.style.position = "absolute"
  nameOverlay.style.bottom = "0"
  nameOverlay.style.left = "0"
  nameOverlay.style["pointer-events"] = "none"
  nameOverlay.style.padding = "4px"
  nameOverlay.style.backgroundColor = "black"
  nameOverlay.style.color = 'white'
  return nameOverlay
}
const hoverWin = (viewer, nameOverlay, pickedFeature, position) => {
  console.log(pickedFeature)
  if (!defined(pickedFeature)) {
    nameOverlay.style.display = "none";
    return;
  }
  // A feature was picked, so show its overlay content
  nameOverlay.style.display = "block";
  nameOverlay.style.bottom = `${
    viewer.canvas.clientHeight - position.y
  }px`;
  nameOverlay.style.left = `${position.x}px`;
  let featureId = pickedFeature.featureId;
  nameOverlay.textContent = featureId;
}
</script>

<style scoped>
.cesium-container {
  width: 100%;
  height: 100%;
  margin: 0 auto;
  position: relative;
  /* background: url('../assets/images/bg.jpg') no-repeat;
  background-size: cover; */
}
</style>
